package dk.aiszone.lang.sql;

import dk.aiszone.lang.sql.interfaces.SQLConstraint;
import dk.aiszone.lang.sql.interfaces.SQLObject;
import dk.aiszone.lang.sql.interfaces.SQLPart;

/**
 * Representation of the equals (=) operator in SQL.
 * 
 * @author Ais
 */
public class SQLEquals extends AbstractSQLObject implements SQLConstraint {

    private final SQLAssignableField assignableField;

    /**
     * Constructor for the <code>SQLEquals</code> object.
     * 
     * @param field
     *            The field to match
     */
    public SQLEquals(SQLAssignableField field) {
        this.assignableField = field;
    }

    @Override
    public SQLResult prepareSQL(SQLResult sql) {
        if (!assignableField.isAssigned()) {
            return sql.append(this);
        }

        sql.append(assignableField.getField());

        Object value = assignableField.getValue();
        if (value != null && SQLObject.class.isAssignableFrom(value.getClass())) {
            sql.append(getOperator());
            return ((SQLObject)value).prepareSQL(sql);
        }
        return sql.append(toSQL(value));
    }

    @Override
    public String toPreparedStatement() {
        StringBuilder sb = new StringBuilder();
        sb.append(assignableField.getField());
        if (assignableField.isAssignable()) {
            return sb.append(" = ?").toString();
        }
        return sb.append(toSQL(assignableField.getValue())).toString();
    }

    @Override
    public String toSQL() {
        StringBuilder sb = new StringBuilder();
        sb.append(assignableField.getField());
        return sb.append(toSQL(assignableField.getValue())).toString();
    }

    /**
     * Retrieve the operator used by the object.
     * 
     * @return <code>String</code> representation of the operator.
     */
    protected String getOperator() {
        return " = ";
    }

    private String toSQL(Object value) {
        if (value == null) {
            return " is null";
        } else if (String.class.equals(value.getClass())) {
            return getOperator() + "'" + (String)value + "'";
        } else if (Boolean.class.equals(value.getClass()) || Number.class.isAssignableFrom(value.getClass())) {
            return getOperator() + value.toString();
        } else if (SQLPart.class.isAssignableFrom(value.getClass())) {
            return getOperator() + ((SQLPart)value).toSQL();
        }

        throw new IllegalArgumentException("Unknown value class: " + value.getClass());
    }

    @Override
    public SQLAssignableField getAssignableField() {
        return assignableField;
    }
}